﻿using StackExchange.Redis;
using System.Collections.Concurrent;

namespace Common.Cache.Redis
{
    public class RedisHelper : IDisposable
    {
        /// <summary>
        /// redis配置
        /// </summary>
        private ConfigurationOptions _redisOptions;
        //实例名称
        private string _instanceName;
        //默认数据库
        private int _defaultDB;

        private ConcurrentDictionary<string, ConnectionMultiplexer> _connections;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="config">redis配置</param>
        /// <exception cref="ArgumentNullException"></exception>
        public RedisHelper(RedisConfig config)
        {
            if (config == null || config.Endpoints == null || config.Endpoints.Count == 0)
            {
                throw new ArgumentNullException("获取Redis配置信息失败");
            }
            var redisOptions = new ConfigurationOptions();
            config.Endpoints.ForEach(c => { redisOptions.EndPoints.Add(c.Host, c.Port); });
            redisOptions.AbortOnConnectFail = false; //获取或设置是否应通过TimeoutException显式通知连接/配置超时
            redisOptions.ServiceName = config.InstanceName;
            redisOptions.Password = config.Password;
            redisOptions.User = config.UserName;
            _redisOptions = redisOptions;
            _instanceName = config.InstanceName;
            _defaultDB = config.DefaultDB;
            _connections = new ConcurrentDictionary<string, ConnectionMultiplexer>();
        }

        /// <summary>
        /// 获取ConnectionMultiplexer
        /// </summary>
        /// <returns></returns>
        private ConnectionMultiplexer GetConnect()
        {
            return _connections.GetOrAdd(_instanceName, p => ConnectionMultiplexer.Connect(_redisOptions));
        }

        /// <summary>
        /// 获取数据库
        /// </summary>
        /// <param name="configName"></param>
        /// <param name="db">默认为0：优先代码的db配置，其次config中的配置</param>
        /// <returns></returns>
        public IDatabase GetDatabase()
        {
            return GetConnect().GetDatabase(_defaultDB);
        }
        public IDatabase GetDatabase(int db)
        {
            return GetConnect().GetDatabase(db);
        }
        //public IServer GetServer(string configName = null, int endPointsIndex = 0)
        //{
        //    var confOption = ConfigurationOptions.Parse(_connectionString);
        //    return GetConnect().GetServer(confOption.EndPoints[endPointsIndex]);
        //}

        public ISubscriber GetSubscriber(string configName = null)
        {
            return GetConnect().GetSubscriber();
        }
        public void Dispose()
        {
            if (_connections != null && _connections.Count > 0)
            {
                foreach (var item in _connections.Values)
                {
                    item.Close();
                }
            }
        }
    }
}
